import 'dart:convert';
import 'package:dio/dio.dart';
import 'dart:io';
import 'package:oauth2/oauth2.dart' as oauth2;
import 'package:safety_platform/authentication.dart';
import 'package:mime/mime.dart';
import 'package:expire_cache/expire_cache.dart';
import 'package:crypto/crypto.dart';
import 'dart:convert';
import 'package:convert/convert.dart';
// HttpClient _httpClient = HttpClient();
// String get aysnc(String url, Map<String,String> prams){

// }
// final mainUrl = 'http://www.safety-saas.com';
final mainUrl = 'http://192.168.3.104:8000';

final _uploadImgUrl = '$mainUrl/core/upload_picture/';
final _uploadFileUrl = '$mainUrl/core/upload_file/';
final tokenEndpoint = Uri.parse("http://www.safety-saas.com/oauth/token/");

final identifier = "biSNqztvIm9QW4GqCNHoTwWBiTrpq89M9xFjnq3J";
final secret =
    "v2J5dobvIPYJLuVHNOlvYFWfAnhUokY1TppV1t5DHDKXJXAcW8kSMdzN6NKfrPZuSJLt62TVDV1HKX0sNEmreZPr7iplJ7CuxtLVUvQd8YbV1U1tlBYCc0anLJsrh6u4";

final username = "182828282828";
final password = "-1234Asdf";

final defaultHeaders = {
  'Content-Type': 'application/json',
  'Accept': 'application/json',
};

final ExpireCache<String,String> _expireCache = ExpireCache<String,String>(
  expireDuration: Duration(seconds: 30)
);
oauth2.Client _client = null;
Future<oauth2.Client> _loadClient() async {
  if (_client == null) {
    var storedToken = await getToken();
    if (storedToken != null) {
      var credentials = oauth2.Credentials.fromJson(storedToken);

      _client =
          oauth2.Client(credentials, identifier: identifier, secret: secret);
    } else {
      _client = await oauth2.resourceOwnerPasswordGrant(
          tokenEndpoint, username, password,
          identifier: identifier, secret: secret);
      setToken(_client.credentials.toJson());
    }
    return _client;
  }
  if (_client.credentials.isExpired) {
    await _client.refreshCredentials();

    //保存credentials
  }
  return _client;
}

/*---------------------------------------------------------------------
*/

Options _options = Options(
  baseUrl: '$mainUrl/api',
  connectTimeout: 5000,
  receiveTimeout: 3000,
);

Dio _dioClient;

Dio _loadHttpClient() {
  if (_dioClient == null) {
    _dioClient = Dio(_options);

    _dioClient.interceptor.request.onSend = (Options options) async {
      String accessToken = await getAccessToken();

      if (accessToken != null) {
        options.headers['Authorization'] = 'Bearer $accessToken';
      }
      print("开始请求[${options.path}]，方法[${options.method}], 参数[${options.data}]");

      options.extra['_startTime'] = DateTime.now().millisecondsSinceEpoch;
      return options;
    };

    _dioClient.interceptor.response.onSuccess = (Response response) async{
      int timeLeaved = -1;
      Options options = response.request;

      // print('wwwwwwwwwww ${options.request}');
      if (options.extra.containsKey('_startTime')) {
        timeLeaved =
            DateTime.now().millisecondsSinceEpoch - options.extra['_startTime'];
      }
      print(
          "返回结果 [${response.statusCode}], 耗时[ $timeLeaved ] ms. 数据[${response.data}]");
      
      if (options.extra.containsKey('_cacheKey')) {
        print('缓存结果');
        _expireCache.set(options.extra['_cacheKey'], json.encode(response.data));
        
      }
      return response;
    };

    _dioClient.interceptor.response.onError = (DioError error) {
      String message = error.message;
      int timeLeaved = -1;
      print('请求网络错误 $error');

      if (error.type == DioErrorType.RESPONSE) {
        Response response = error.response;
        Options options = response.request;
        if (options.extra.containsKey('_startTime')) {
          timeLeaved = DateTime.now().millisecondsSinceEpoch -
              options.extra['_startTime'];
        }
        print(
            "返回结果 [${response.statusCode}], 耗时[ $timeLeaved ] ms. 数据[${response.data}, 消息[$message]]");
      } else {
        print('请求网络返回 ${error.message}');
      }

      // Options options = response.request;

      // print('wwwwwwwwwww ${options.request}');
      // if (options.extra.containsKey('_startTime')) {
      //   timeLeaved =
      //       DateTime.now().millisecondsSinceEpoch - options.extra['_startTime'];
      // }
      // print(
      //     "返回结果 [${response.statusCode}], 耗时[ $timeLeaved ] ms. 数据[${response.data}, 消息[$message]]");

      return error;
    };
  }
  return _dioClient;
}

// _options.merge();

// var sss = Dio;

// sss.toString();

//_dio.interceptor.request.onSend = (Options options){
//      // Do something before request is sent
//      return options; //continue
//      // If you want to resolve the request with some custom data，
//      // you can return a `Response` object or return `dio.resolve(data)`.
//      // If you want to reject the request with a error message,
//      // you can return a `DioError` object or return `dio.reject(errMsg)`
//  };
// _dio.interceptor.request.onSend;
// client.o
// client.options.baseUrl="https://www.xx.com/api" ;
// client.options.connectTimeout = 5000; //5s
// client.options.receiveTimeout=3000;

Future<dynamic> httpGet(String url,
    {Map<String, String> data, Map<String, dynamic> extra,bool cache:false, cancelToken}) async {
  var client = _loadHttpClient();

  Map<String,dynamic> newExtra = extra?? {};

  if (cache) {
      var content = new Utf8Encoder().convert(url);
      var digest = md5.convert(content);
      String key = digest.toString();

      print('缓存Key为: $key');

      String result = await _expireCache.get(key);

      print('从缓存读取，结果为: $result');
      if (result != null) {
        return json.decode(result);
      } else {
        newExtra['_cacheKey'] = key;
      }
  }
  // Dio client = Dio();
  // client.options.baseUrl = "http://www.safety-saas.com/api";
  // Response<String> res = await  client.get<String>(url, data:data);
  Options options = _options.merge(extra: newExtra);
  Response res = await client.get(url, data: data, options: options,cancelToken: cancelToken);
  return res.data;
}

Future<dynamic> httpUpload(File file, {String target}) async {
  Map<String, dynamic> form = Map();
  FileStat stat = file.statSync();
  String name = file.path;

  int index = name.lastIndexOf('/');
  if (index > 0) {
    name = name.substring(index + 1);
  }
  form['file'] = new UploadFileInfo(file, name);
  if (target != null) {
    form['target'] = target;
  }
  form['type'] = lookupMimeType(file.uri.toString());
  // form['type'] = stat.type;

  // form.addAll(ext);
  FormData formData = FormData.from(form);
  Dio dio = Dio();
  // dio.post(_uploadFileUrl, data: formData);
  Response res = await dio.post(_uploadFileUrl, data: formData);

  return res.data;
}

Future<dynamic> httpUploadImg(File file, String fileName,
    {Map<String, dynamic> ext}) async {
  Map<String, dynamic> form = Map();

  form['file'] = new UploadFileInfo(file, fileName);

  form.addAll(ext);
  FormData formData = FormData.from(form);
  Dio dio = Dio();
  Response res = await dio.post(_uploadImgUrl, data: formData);

  return res.data;
}

Future<dynamic> httpPost(String url,
    {Map<String, dynamic> data, Map<String, dynamic> extra}) async {
  var client = _loadHttpClient();
  Options options = _options.merge(extra: extra);
  // DioError
  Response res = await client.post(url, data: data, options: options);
  return res.data;
}

Future<dynamic> httpPut(String url,
    {Map<String, dynamic> data, Map<String, dynamic> extra}) async {
  var client = _loadHttpClient();

  Options options = _options.merge(extra: extra);
  Response res = await client.put(url, data: data, options: options);
  return res.data;
}

Future<String> post(String url) async {
  // json.decode(source)
}

Future<Null> login(String loginName, String password) async {
  try {
    _client = await oauth2.resourceOwnerPasswordGrant(
        tokenEndpoint, loginName, password,
        identifier: identifier, secret: secret);
    setToken(_client.credentials.toJson());
    setLastUser(loginName);
  } on oauth2.AuthorizationException catch (ae) {
    print('登录错误: $ae');
    throw Exception('用户或密码不正确');
  }
}

Future<String> get(String url, [Map<String, String> headers,bool cache]) async {
  var _client = await _loadClient();
  if (headers == null) {
    headers = Map.from(defaultHeaders);
  }
  var res = await _client.get('${mainUrl}${url}', headers: headers);

  if (res.statusCode != 200) {
    throw Exception(res.statusCode);
  }
  Encoding encoding = Encoding.getByName('utf-8');
  return encoding.decode(res.bodyBytes);
}

// main() async {
//   var d = await get('http://10.241.71.64:7983/api/plan/',null);
//   print(d);
// }
